"""
基于激活码的用户管理系统服务层
处理激活码管理、用户管理、权限管理等功能
"""
import logging
from datetime import datetime, date, timedelta
from typing import List, Dict, Any, Optional, Tuple
import jwt
from dataclasses import asdict

from .connection import db_manager
from .user_models import (
    User, UserRole, UserStatus, ActivationCode, CodeType, 
    UserActivityLog, ServicePackage
)

logger = logging.getLogger(__name__)

class UserService:
    """用户管理服务类"""
    
    def __init__(self):
        self.db = db_manager
        self.jwt_secret = "your-secret-key"  # 应该从配置文件读取
    
    # ==================== 激活码管理 ====================
    
    async def create_activation_code(self, code_data: Dict[str, Any]) -> Optional[ActivationCode]:
        """创建激活码"""
        try:
            with self.db.get_cursor() as cursor:
                cursor.execute("""
                    INSERT INTO activation_codes (
                        code, code_type, role, trial_days, subscription_days, 
                        max_users, created_by, expires_at, description
                    ) VALUES (%s, %s, %s, %s, %s, %s, %s, %s, %s)
                """, (
                    code_data['code'],
                    code_data['code_type'].value if isinstance(code_data['code_type'], CodeType) else code_data['code_type'],
                    code_data['role'].value if isinstance(code_data['role'], UserRole) else code_data['role'],
                    code_data.get('trial_days', 0),
                    code_data.get('subscription_days', 0),
                    code_data.get('max_users', 1),
                    code_data.get('created_by'),
                    code_data.get('expires_at'),
                    code_data.get('description')
                ))
                
                code_id = cursor.lastrowid
                logger.info(f"激活码创建成功: {code_data['code']} (ID: {code_id})")
                return await self.get_activation_code_by_id(code_id)
                
        except Exception as e:
            logger.error(f"创建激活码失败: {e}")
            return None
    
    async def get_activation_code_by_code(self, code: str) -> Optional[ActivationCode]:
        """根据激活码获取激活码信息"""
        try:
            with self.db.get_cursor() as cursor:
                cursor.execute("""
                    SELECT * FROM activation_codes WHERE code = %s
                """, (code,))
                
                row = cursor.fetchone()
                if row:
                    return self._row_to_activation_code(row)
                return None
                
        except Exception as e:
            logger.error(f"获取激活码失败: {e}")
            return None
    
    async def get_activation_code_by_id(self, code_id: int) -> Optional[ActivationCode]:
        """根据ID获取激活码信息"""
        try:
            with self.db.get_cursor() as cursor:
                cursor.execute("""
                    SELECT * FROM activation_codes WHERE id = %s
                """, (code_id,))
                
                row = cursor.fetchone()
                if row:
                    return self._row_to_activation_code(row)
                return None
                
        except Exception as e:
            logger.error(f"获取激活码失败: {e}")
            return None
    
    async def use_activation_code(self, code: str, user_id: int) -> bool:
        """使用激活码"""
        try:
            with self.db.get_cursor() as cursor:
                cursor.execute("""
                    UPDATE activation_codes 
                    SET used_by = %s, used_at = %s, updated_at = %s
                    WHERE code = %s
                """, (user_id, datetime.now(), datetime.now(), code))
                
                logger.info(f"激活码使用成功: {code} -> 用户ID: {user_id}")
                return True
                
        except Exception as e:
            logger.error(f"使用激活码失败: {e}")
            return False
    
    # ==================== 用户管理 ====================
    
    async def create_user(self, user_data: Dict[str, Any]) -> Optional[User]:
        """创建新用户（基于激活码）"""
        try:
            # 自动生成用户名
            username = f"user_{user_data['activation_code_id']}_{int(datetime.now().timestamp())}"
            
            # 计算试用期和订阅期
            trial_start = date.today()
            trial_end = None
            subscription_start = None
            subscription_end = None
            
            if user_data.get('trial_days', 0) > 0:
                trial_end = trial_start + timedelta(days=user_data['trial_days'])
            
            if user_data.get('subscription_days', 0) > 0:
                subscription_start = trial_end if trial_end else trial_start
                subscription_end = subscription_start + timedelta(days=user_data['subscription_days'])
            
            with self.db.get_cursor() as cursor:
                cursor.execute("""
                    INSERT INTO users (
                        username, role, status, trial_start_date, trial_end_date,
                        subscription_start_date, subscription_end_date, promotion_admin_id,
                        activation_code_id, created_at, updated_at
                    ) VALUES (%s, %s, %s, %s, %s, %s, %s, %s, %s, %s, %s)
                """, (
                    username,
                    user_data['role'].value if isinstance(user_data['role'], UserRole) else user_data['role'],
                    user_data.get('status', UserStatus.ACTIVE).value if isinstance(user_data.get('status'), UserStatus) else user_data.get('status', 'active'),
                    trial_start,
                    trial_end,
                    subscription_start,
                    subscription_end,
                    user_data.get('promotion_admin_id'),
                    user_data['activation_code_id'],
                    datetime.now(),
                    datetime.now()
                ))
                
                user_id = cursor.lastrowid
                
                # 记录操作日志（只有在有创建者时才记录）
                created_by = user_data.get('created_by')
                if created_by and created_by > 0:
                    await self.log_user_activity(
                        created_by,
                        'create_user',
                        'user',
                        user_id,
                        f"创建用户: {username}"
                    )
                
                logger.info(f"用户创建成功: {username} (ID: {user_id})")
                return await self.get_user_by_id(user_id)
                
        except Exception as e:
            logger.error(f"创建用户失败: {e}")
            return None
    
    async def get_user_by_id(self, user_id: int) -> Optional[User]:
        """根据ID获取用户"""
        try:
            with self.db.get_cursor() as cursor:
                cursor.execute("""
                    SELECT * FROM users WHERE id = %s
                """, (user_id,))
                
                row = cursor.fetchone()
                if row:
                    return self._row_to_user(row)
                return None
                
        except Exception as e:
            logger.error(f"获取用户失败: {e}")
            return None
    
    async def get_user_by_username(self, username: str) -> Optional[User]:
        """根据用户名获取用户"""
        try:
            with self.db.get_cursor() as cursor:
                cursor.execute("""
                    SELECT * FROM users WHERE username = %s
                """, (username,))
                
                row = cursor.fetchone()
                if row:
                    return self._row_to_user(row)
                return None
                
        except Exception as e:
            logger.error(f"获取用户失败 (用户名: {username}): {e}")
            return None
    
    async def update_user_login_info(self, user_id: int):
        """更新用户登录信息"""
        try:
            with self.db.get_cursor() as cursor:
                cursor.execute("""
                    UPDATE users 
                    SET last_login_at = %s, login_count = login_count + 1, updated_at = %s
                    WHERE id = %s
                """, (datetime.now(), datetime.now(), user_id))
                
        except Exception as e:
            logger.error(f"更新用户登录信息失败: {e}")
    
    async def get_users_by_role(self, role: str, page: int = 1, page_size: int = 20) -> Tuple[List[User], int]:
        """根据角色获取用户列表"""
        try:
            offset = (page - 1) * page_size
            with self.db.get_cursor() as cursor:
                # 获取总数
                cursor.execute("SELECT COUNT(*) FROM users WHERE role = %s", (role,))
                total = cursor.fetchone()[0]
                
                # 获取用户列表
                cursor.execute("""
                    SELECT * FROM users WHERE role = %s 
                    ORDER BY created_at DESC LIMIT %s OFFSET %s
                """, (role, page_size, offset))
                
                rows = cursor.fetchall()
                users = [self._row_to_user(row) for row in rows]
                return users, total
                
        except Exception as e:
            logger.error(f"获取用户列表失败: {e}")
            return [], 0
    
    async def get_all_users(self, page: int = 1, page_size: int = 20) -> Tuple[List[User], int]:
        """获取所有用户列表"""
        try:
            offset = (page - 1) * page_size
            with self.db.get_cursor() as cursor:
                # 获取总数
                cursor.execute("SELECT COUNT(*) FROM users")
                total = cursor.fetchone()[0]
                
                # 获取用户列表
                cursor.execute("""
                    SELECT * FROM users 
                    ORDER BY created_at DESC LIMIT %s OFFSET %s
                """, (page_size, offset))
                
                rows = cursor.fetchall()
                users = [self._row_to_user(row) for row in rows]
                return users, total
                
        except Exception as e:
            logger.error(f"获取用户列表失败: {e}")
            return [], 0
    
    async def extend_user_trial(self, user_id: int, days: int) -> bool:
        """延长用户试用期"""
        try:
            with self.db.get_cursor() as cursor:
                cursor.execute("""
                    UPDATE users 
                    SET trial_end_date = DATE_ADD(trial_end_date, INTERVAL %s DAY),
                        updated_at = %s
                    WHERE id = %s
                """, (days, datetime.now(), user_id))
                
                return cursor.rowcount > 0
                
        except Exception as e:
            logger.error(f"延长试用期失败: {e}")
            return False
    
    async def update_user_status(self, user_id: int, status: str) -> bool:
        """更新用户状态"""
        try:
            with self.db.get_cursor() as cursor:
                cursor.execute("""
                    UPDATE users 
                    SET status = %s, updated_at = %s
                    WHERE id = %s
                """, (status, datetime.now(), user_id))
                
                return cursor.rowcount > 0
                
        except Exception as e:
            logger.error(f"更新用户状态失败: {e}")
            return False
    
    # ==================== 激活码管理 ====================
    
    async def get_activation_codes_by_creator(self, creator_id: int, page: int = 1, page_size: int = 20) -> Tuple[List[ActivationCode], int]:
        """获取指定创建者创建的激活码列表"""
        try:
            offset = (page - 1) * page_size
            with self.db.get_cursor() as cursor:
                # 获取总数
                cursor.execute("SELECT COUNT(*) FROM activation_codes WHERE created_by = %s", (creator_id,))
                total = cursor.fetchone()[0]
                
                # 获取激活码列表
                cursor.execute("""
                    SELECT * FROM activation_codes WHERE created_by = %s 
                    ORDER BY created_at DESC LIMIT %s OFFSET %s
                """, (creator_id, page_size, offset))
                
                rows = cursor.fetchall()
                codes = [self._row_to_activation_code(row) for row in rows]
                return codes, total
                
        except Exception as e:
            logger.error(f"获取激活码列表失败: {e}")
            return [], 0
    
    # ==================== JWT令牌管理 ====================
    
    def generate_jwt_token(self, user: User) -> str:
        """生成JWT令牌"""
        payload = {
            'user_id': user.id,
            'username': user.username,
            'role': user.role.value,
            'exp': datetime.utcnow() + timedelta(days=30)
        }
        return jwt.encode(payload, self.jwt_secret, algorithm='HS256')
    
    def verify_jwt_token(self, token: str) -> Optional[Dict[str, Any]]:
        """验证JWT令牌"""
        try:
            payload = jwt.decode(token, self.jwt_secret, algorithms=['HS256'])
            return payload
        except jwt.ExpiredSignatureError:
            logger.warning("JWT令牌已过期")
            return None
        except jwt.InvalidTokenError:
            logger.warning("JWT令牌无效")
            return None
    
    def generate_jwt_token_from_data(self, user_data: Dict[str, Any]) -> str:
        """根据用户数据生成JWT令牌"""
        try:
            payload = {
                'user_id': user_data['user_id'],
                'username': user_data['username'],
                'role': user_data['role'],
                'exp': datetime.now() + timedelta(days=30)  # 30天过期
            }
            token = jwt.encode(payload, self.jwt_secret, algorithm='HS256')
            return token
        except Exception as e:
            logger.error(f"生成JWT令牌失败: {e}")
            return None
    
    # ==================== 活动日志 ====================
    
    async def log_user_activity(self, user_id: int, action: str, target_type: str, 
                               target_id: int, details: str, ip_address: str = None, 
                               user_agent: str = None):
        """记录用户活动"""
        try:
            with self.db.get_cursor() as cursor:
                cursor.execute("""
                    INSERT INTO user_activity_logs (
                        user_id, action, target_type, target_id, details, 
                        ip_address, user_agent, created_at
                    ) VALUES (%s, %s, %s, %s, %s, %s, %s, %s)
                """, (user_id, action, target_type, target_id, details, 
                     ip_address, user_agent, datetime.now()))
                
        except Exception as e:
            logger.error(f"记录用户活动失败: {e}")
    
    # ==================== 数据转换方法 ====================
    
    def _row_to_user(self, row) -> User:
        """将数据库行转换为User对象"""
        # 处理字典格式的查询结果
        if isinstance(row, dict):
            return User(
                id=row['id'],
                username=row['username'],
                role=UserRole(row['role']),
                status=UserStatus(row['status']),
                trial_start_date=row['trial_start_date'],
                trial_end_date=row['trial_end_date'],
                subscription_start_date=row['subscription_start_date'],
                subscription_end_date=row['subscription_end_date'],
                promotion_admin_id=row['promotion_admin_id'],
                activation_code_id=row['activation_code_id'],
                last_login_at=row['last_login_at'],
                login_count=row['login_count'],
                created_at=row['created_at'],
                updated_at=row['updated_at']
            )
        else:
            # 处理元组格式的查询结果
            return User(
                id=row[0],
                username=row[1],
                role=UserRole(row[2]),
                status=UserStatus(row[3]),
                trial_start_date=row[4],
                trial_end_date=row[5],
                subscription_start_date=row[6],
                subscription_end_date=row[7],
                promotion_admin_id=row[8],
                activation_code_id=row[9],
                last_login_at=row[10],
                login_count=row[11],
                created_at=row[12],
                updated_at=row[13]
            )
    
    def _row_to_activation_code(self, row) -> ActivationCode:
        """将数据库行转换为ActivationCode对象"""
        # 处理字典格式的查询结果
        if isinstance(row, dict):
            return ActivationCode(
                id=row['id'],
                code=row['code'],
                code_type=CodeType(row['code_type']),
                role=UserRole(row['role']),
                trial_days=row['trial_days'],
                subscription_days=row['subscription_days'],
                max_users=row['max_users'],
                created_by=row['created_by'],
                used_by=row['used_by'],
                used_at=row['used_at'],
                is_active=bool(row['is_active']),
                expires_at=row['expires_at'],
                description=row['description'],
                created_at=row['created_at'],
                updated_at=row['updated_at']
            )
        else:
            # 处理元组格式的查询结果
            return ActivationCode(
                id=row[0],
                code=row[1],
                code_type=CodeType(row[2]),
                role=UserRole(row[3]),
                trial_days=row[4],
                subscription_days=row[5],
                max_users=row[6],
                created_by=row[7],
                used_by=row[8],
                used_at=row[9],
                is_active=bool(row[10]),
                expires_at=row[11],
                description=row[12],
                created_at=row[13],
                updated_at=row[14]
            )

# 创建全局用户服务实例
user_service = UserService()
